Skip to content

fix(agc): preserve CPU writes after resident linear target draws - #8246

Open
MarcZX10 wants to merge 31 commits into
boykopovar:mainfrom
MarcZX10:codex/8152-linear-target-ordering
Open

MarcZX10 wants to merge 31 commits into
boykopovar:mainfrom
MarcZX10:codex/8152-linear-target-ordering

Conversation

@MarcZX10

@MarcZX10 MarcZX10 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What

Fixes #8152: a later write-back from a recorded linear-target draw could overwrite CPU stores made after Draw returned.

This PR uses the coordinated implementation authored by Rajveer Shekhawat (two commits) and the concurrent-byte correction authored by embersas. The original three commits were split into a series of smaller ones, so each commit derived from their work carries Co-authored-by trailers for both; the drawn-rectangle fix (leave the drawn-rectangle store to targets without a draw snapshot) and the final Refresh() commit are mine and carry none. It snapshots the resident image around a recorded linear draw and merges changed bytes through the linear detiler so untouched guest bytes and CPU writes survive. The regression coverage includes seeded and unseeded partial draws, masked channels, partial geometry, later blending, queued overlapping draws, cached-recipe replay and GPU detiles for supported element widths.

This is separate from #1191's resident-target performance path and #7154's depth-plane buffer coherence. It does not depend on either PR.

Tested

Current head db12f5d6fb (30 commits, rebased onto main 3fea2a937b):

  • Linux, GCC 12.2, lavapipe (LLVM 15.0.6), host CPU gate disabled in a throwaway copy of the tree because this Xeon E5-1620 v2 lacks AVX2 and FMA. All 23 agc_driver_linear_target_* tests plus agc_driver_graphics: 22 pass and 2 skip on lavapipe (direct_write_completion, import_creation). With ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation there are 0 VUID- lines (the layer is inserted at instance and device level). The same run on main is not posted yet.
  • Memory and cost in a throwaway harness (3 targets of 24 MiB, 5 to 60 draws per target): peak RSS +72 to 76 MiB over main, flat in the number of draws and targets (one live snapshot per draw). Per-draw cost was measured only with the guest memory not write-watched (kernel 6.1, no write watch), where the target is compared or uploaded whole: about 44 ms on main and 74 to 99 ms with this PR depending on whether the CPU writes before each draw. No number from a write-watched host and no tools/trace_digest.py summary are available yet. Details are in the comments below.
  • python3 tools/check_conventions.py --base upstream/main and git diff --check pass.

Earlier reports, on older heads and not repeated on this one:

  • On pre-rebase head e5b9ac546 against base 3fd1cc393, the author reports 36/36 fresh focused runs passed on NVIDIA RTX 5070 (driver 617.42) and AMD Radeon(TM) Graphics (driver 32.0.21030.2001), Windows 11 Pro 26200, GCC 15.2 Release with SPIRV-Tools and Khronos validation/synchronization validation enabled, with no new VUIDs or validation warnings, and 118/118 common selected tests per GPU on both base and change.
  • Embersas supplied the concurrent-byte correction in comment 6289116592: on the correction tree before an older rebase (local revision fea0c0cd8a2e8f85454e0d4b5b917915e0e3035b), 15/15 focused tests and 20/20 repeated key-case executions on a Windows 11 RTX 4070 Laptop, NVIDIA 592.82, with Khronos synchronization validation. The concurrent regression recorded 5,668 lost CPU updates on the then-current head and the original unseeded control on main lost 7,680 of 8,192 CPU-written bytes; the corrected cases passed 20/20 repeats with zero lost updates.
  • No Linux/macOS write-watched runtime, console, title or performance result is claimed for the current head.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: AGC: a recorded draw into a resident linear color target stores the whole target back over CPU stores made after the draw #8152
  • Unblocks: none
  • GPUs tested: none on the current head beyond lavapipe (llvmpipe, Linux); NVIDIA RTX 5070 / driver 617.42 and AMD Radeon(TM) Graphics / driver 32.0.21030.2001 on Windows 11 Pro 26200 (reported on pre-rebase head e5b9ac546); NVIDIA RTX 4070 Laptop / driver 592.82 on Windows 11 Pro (reported by Embersas on an older correction tree)
  • AI-assisted: yes

@MarcZX10
MarcZX10 force-pushed the codex/8152-linear-target-ordering branch from bcf6733 to b2ed1d9 Compare October 20, 2026 06:51
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 862 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 1896 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4448 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 4472 docs/dev/ENVIRONMENT.md
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6108 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6146 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6185 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 6186 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6194 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6197 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/libs/prx/libSceAgcDriver/tests/GraphicsTests.hpp
PR 6412 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6481 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/libs/prx/libSceAgcDriver/tests/GraphicsTests.hpp
PR 6501 docs/dev/ENVIRONMENT.md
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6615 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6804 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6905 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/shaders/TextureDetile.comp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
PR 6924 docs/dev/ENVIRONMENT.md
PR 6970 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6973 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6987 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6989 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6995 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 7002 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 7085 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
core/libs/prx/libSceAgcDriver/tests/GraphicsTests.hpp
PR 7223 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7275 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7369 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7410 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7449 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
docs/dev/ENVIRONMENT.md
PR 7457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7508 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7514 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 7642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/shaders/TextureDetile.comp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 7643 docs/dev/ENVIRONMENT.md
PR 7668 core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8004 docs/dev/ENVIRONMENT.md
PR 8212 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8484 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
docs/dev/ENVIRONMENT.md
PR 8592 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8707 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 8963 docs/dev/ENVIRONMENT.md
PR 9012 docs/dev/ENVIRONMENT.md
PR 9020 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9154 docs/dev/ENVIRONMENT.md
PR 9248 docs/dev/ENVIRONMENT.md
PR 9289 docs/dev/ENVIRONMENT.md
PR 9335 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9345 docs/dev/ENVIRONMENT.md
PR 9356 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 9387 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 9489 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9508 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/shaders/TextureDetile.comp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 9604 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9671 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9674 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
PR 9675 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9676 docs/dev/ENVIRONMENT.md
PR 9700 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9712 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 9748 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9852 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 9875 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 9884 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 9891 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9895 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9897 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9898 docs/dev/ENVIRONMENT.md
PR 9915 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9999 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10043 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 10049 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10064 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10069 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 10141 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10159 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10193 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/shaders/TextureDetile.comp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 10233 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10249 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10256 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10351 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10359 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10442 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 10443 docs/dev/ENVIRONMENT.md
PR 10472 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 10497 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 10556 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10656 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10668 docs/dev/ENVIRONMENT.md
PR 10678 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 10743 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10757 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 10779 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10867 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10894 docs/dev/ENVIRONMENT.md
PR 10920 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 11265 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 11351 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 11435 docs/dev/ENVIRONMENT.md
PR 11436 docs/dev/ENVIRONMENT.md
PR 11444 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 11452 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 11485 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 11551 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 11557 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 11566 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 11825 core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 11948 docs/dev/ENVIRONMENT.md
PR 11995 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 11998 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 12066 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 12070 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12120 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 12125 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 12132 docs/dev/ENVIRONMENT.md
PR 12323 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 12324 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 12478 docs/dev/ENVIRONMENT.md
PR 12544 docs/dev/ENVIRONMENT.md
PR 12567 docs/dev/ENVIRONMENT.md
PR 12568 docs/dev/ENVIRONMENT.md
PR 12617 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12662 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 12696 docs/dev/ENVIRONMENT.md
PR 12720 docs/dev/ENVIRONMENT.md
PR 12745 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 12746 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 12764 docs/dev/ENVIRONMENT.md
PR 12792 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12813 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12828 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 12840 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 12849 docs/dev/ENVIRONMENT.md
PR 12855 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 12921 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 12980 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 12994 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 13021 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13023 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13044 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 13131 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 13147 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13148 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13159 docs/dev/ENVIRONMENT.md
PR 13169 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 13178 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13251 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 13262 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 13263 docs/dev/ENVIRONMENT.md
PR 13646 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 13793 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 13796 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 13809 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 13858 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 13863 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 13920 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 13928 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/shaders/TextureDetile.comp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 13929 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/shaders/TextureDetile.comp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/ENVIRONMENT.md
PR 13991 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14032 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14051 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/ENVIRONMENT.md
PR 14076 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14220 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 14235 docs/dev/ENVIRONMENT.md
PR 14243 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14260 docs/dev/ENVIRONMENT.md
PR 14261 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 14262 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 14264 docs/dev/ENVIRONMENT.md
PR 14299 docs/dev/ENVIRONMENT.md
PR 14302 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 14311 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 14344 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
docs/dev/ENVIRONMENT.md
PR 14367 docs/dev/ENVIRONMENT.md
PR 14473 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14561 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14621 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14628 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 14794 docs/dev/ENVIRONMENT.md
PR 14838 docs/dev/ENVIRONMENT.md
PR 14857 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 14868 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 14880 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 14904 docs/dev/ENVIRONMENT.md
PR 14909 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 14914 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 14943 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/ENVIRONMENT.md
PR 14944 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 15004 docs/dev/ENVIRONMENT.md
PR 15015 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 15056 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 15058 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 15059 docs/dev/ENVIRONMENT.md
PR 15064 docs/dev/ENVIRONMENT.md
PR 15067 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp

@MarcZX10
MarcZX10 marked this pull request as draft October 20, 2026 06:56
@MarcZX10

Copy link
Copy Markdown
Contributor Author

I marked this PR draft after a second correctness review. Deferring writeback alone is insufficient: the current write-watch policy preserves whole 64 KiB blocks, which can discard the draw output in the same block as a post-draw CPU store. Also, a writeback recorded during a completion needs to execute synchronously rather than remain in a newly opened recorder batch. I am working through a region-aware writeback path and will update the PR when the regression and completion ordering are addressed.

@github-actions github-actions Bot added the fix error Closes an issue (Fixes #N) label Oct 20, 2026
@MarcZX10

Copy link
Copy Markdown
Contributor Author

Update after checking the reporter’s run on current main: my earlier proposed keep-block explanation was wrong. The seed causes a re-upload after the CPU write, and the draw completion flush happens before later CPU writes. The unseeded, different-output case demonstrates the actual whole-target writeback ordering bug. I also found a lifecycle blocker in my attempted deferral: cache eviction marks a texture released, which makes FlushPending ignore it. I discarded that incomplete local attempt; the published branch remains draft while I work out a fix that keeps the pending image discoverable and orders its later writeback at the access that needs it.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

I pushed two commits to #8246: fe29558e94 defers linear target eviction writeback and records the draw as a pending writer; 285884da27 updates the regression to flush and wait for readback before checking memory. The writeback keeps changed CPU bytes within the same 64 KiB block while storing the remaining GPU bytes. The focused target builds and links locally, conventions pass, and CTest is blocked before Vulkan initialization by this host CPU’s missing required extensions. I have kept the PR as a draft pending a run on a supported CPU/GPU.

@fogydes fogydes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff, CI, and verified the existing test on current main.

Production code (Draw.cpp): The fix defers the resident linear color target writeback from draw-recording time to batch completion via recorder.OnComplete(). Before this change, StorageTexture::FlushPending ran synchronously during recording — scheduling a whole-target copyout before any CPU stores the game makes after Draw returns. At completion, the OnComplete lambda:

  1. Acquires GuestMemory::GpuMutex() — correct, since FlushPending and WriteBack mutate shared guest-memory state.
  2. Flushes pending overlapping aliases (preserving prior alias reconciliation behavior).
  3. Calls keep->WriteBack() to write the GPU results back.

The keep shared_ptr capture extends the resident's lifetime until the completion callback runs, preventing a use-after-free if the texture is otherwise released. This is sound.

Test (LinearTargetResident.cpp): The regression sequence is well-designed:

  • Program() now takes a blueConstant parameter (default 0x80), allowing the second draw to write a distinct blue value (0xf4).
  • Draw() now takes scissorWidth (default Width), allowing a left-scissored second draw.
  • The run lambda executes two draws: full-width blue=0x80, then left-half blue=0xf4. Between draws, the seed variant writes 0x5a to the left half of the CPU buffer. After both draws, the CPU writes 0x42 to the right half. After WaitIdle(), it checks:
    • Left half: second draw's output (x, y, 2.0, 1.0 with 0xf4 blue → float 2.0 via v_mov_b32 encoding) preserved.
    • Right half: CPU-written 0x42 bytes preserved (not overwritten by GPU writeback).
  • Both run(true) (seeded) and run(false) (unseeded) are exercised.

The instruction encoding 0x7e000200u | blueConstant | (22u << 17u) is a v_mov_b32 with an inline constant — the constant index formula is correct for GCN/RDNA ISA.

CI: conventions, labels pass. Build/platform jobs skip (AGC change, no CI GPU runner).

Local verification: Built agc_driver_linear_target_resident_tests and ran ctest -R "^agc_driver_linear_target_resident$" -V with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 on current main — Passed (0.56s, NVIDIA GeForce RTX 5050 Laptop GPU). The test passes on the existing code; the enhanced test from this PR would exercise the new writeback path.

PR body: Honest about the hardware limitation (Xeon E5-1620 v2 can't run Vulkan tests). Template complete.

One observation: the PR doesn't note VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation testing, but the host CPU guard prevents the runtime from reaching Vulkan initialization anyway, so this is consistent with the limitation.

No blocking issues found.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

Follow-up: I found the first byte-merge revision could compare against an upload baseline that was stale across recorded draws. Commit ec9d6fecb5 snapshots guest bytes immediately before each recorded linear draw and uses CPU-specific write stamps when preserving changed bytes. The focused target rebuilt and linked successfully; runtime remains blocked before Vulkan initialization by the host CPU feature guard. I have kept the PR draft.

@github-actions github-actions Bot added the agc libSceAgc* label Oct 20, 2026
@MarcZX10

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review and for checking the previous code on your RTX 5050. Since that review, the fix changed: it now leaves target results pending after batch completion and stores them on the later read/flush path; commit ec9d6fecb5 also refreshes the byte baseline before each draw, and 50f477fccc reuses the full guest snapshot rather than limiting byte merging to 1 MiB. I rebuilt the focused target, but this Xeon host is stopped by the CPU feature guard before Vulkan. If you have time, could you run the current draft head (50f477fccc) through agc_driver_linear_target_resident on your GPU? The PR remains draft while that runtime behavior is unverified here.

@MarcZX10
MarcZX10 marked this pull request as ready for review October 20, 2026 07:46
@rajvveer

rajvveer commented Oct 20, 2026 •

Copy link
Copy Markdown

Sharing a tested alternative implementation and regression coverage for #8152 so we can coordinate with this PR.

Branch: rajvveer/AnyPS5 — fix/agc-linear-target-cpu-writes

This approach captures the actual image on the GPU before a recorded linear draw and merges only changed bytes into guest memory. Atomic word updates preserve untouched channels sharing a word. Image and guest baselines remain separate for subsequent refresh; CPU write-back and padded array layers are covered too. It keeps the recorded path.

The tests extend Celegans12's reproducer: seeded/unseeded partial draws, masked float/RGBA8 channels, partial geometry, later blending, queued overlapping draws, actual cached-recipe replay, and GPU retile cases for 1/2/4/8/16-byte elements. Recipe replay is unseeded so a deferred re-upload cannot mask the original bug.

Validation: Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7, Release with SPIRV-Tools; NVIDIA RTX 5070 (617.42) and AMD Radeon(TM) Graphics (32.0.21030.2001).

  • Independently built base 3fd1cc393: the compatible regression overlay reproduces the overwrite on both GPUs; synchronous controls pass.
  • 36/36 fresh focused runs passed at e5b9ac546, with the correct devices and Khronos 1.4.363 layer verified, synchronization validation enabled, and no validation errors/warnings or skips. This includes five modes plus actual recipe replay.
  • 118/118 common selected tests per GPU passed on base and change. Existing broader-suite diagnostics matched by test name, message and count: NVIDIA 5 errors/10 warnings; AMD 6 errors/10 warnings. No new VUIDs; this is not a claim that the entire suite is validation-clean.
  • Full runtime/relinker builds pass. The paired suite preceded the final recipe-only test tightening; production code was unchanged, and the final build/focused runs were repeated.

These results apply to the linked branch; I have not executed this PR's current 50f477fccc head. No real-title, Linux/macOS, console or performance result is claimed. The snapshot adds GPU work and temporary memory.

Would incorporating the implementation or regression coverage here be useful, or would you prefer a coordinated alternative PR? I have kept the separate PR on hold.

@MarcZX10
MarcZX10 force-pushed the codex/8152-linear-target-ordering branch from 50f477f to e32a19b Compare October 20, 2026 08:46
@MarcZX10

Copy link
Copy Markdown
Contributor Author

I chose to integrate your implementation and regression commits into #8246 rather than open a second PR for the same issue. Both commits remain authored by you (unknown <rajveershekhawat626@gmail.com> as recorded in Git), and the head is now e32a19b4d7957795a3b5cf21848b41889bd193a5, rebased on current main 35fa2bdd. The older-base GPU/build results and the rebase validation limits are now explicit in the PR description. Could you rerun the focused matrix on this exact head when possible? I will keep the draft open pending that current-head check.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

Correction to my previous note: I said I would keep the PR draft open, but GitHub shows it was already marked ready for review at 07:46 UTC. I had the state wrong; I did not change the draft/ready setting as part of integrating your commits. The PR remains ready for review, with the current-head runtime rerun still outstanding.

@github-actions github-actions Bot added the build label Oct 20, 2026
@rajvveer

Copy link
Copy Markdown

The requested exact-head rerun is complete: e32a19b4d7957795a3b5cf21848b41889bd193a5 was rebuilt in a separate clean worktree and passed 36/36 focused executions. agc_driver_graphics passed too. Independently rebuilt main 35fa2bdd also passed the default resident control on both GPUs.

Hardware: Windows 11 Pro 26200, NVIDIA GeForce RTX 5070 / driver 617.42, and AMD Radeon(TM) Graphics / driver 32.0.21030.2001; GCC 15.2.0 Release with SPIRV-Tools.

The matrix was five resident modes (default, unwatched, draw transitions, eager write-back, synchronous linear targets) plus cached-recipe replay, three repetitions on each GPU. Every process confirmed the intended GPU and loaded Khronos validation layer, with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and synchronization validation enabled. Zero VUIDs, synchronization hazards, validation errors/warnings or skips.

A small test-only follow-up is also available: 66f62d174 — strengthen linear target replay and array coverage. It changes only LinearTargetResident.cpp and applies cleanly to e32a19b4:

  • Capture draws a quarter-width area; cached replay draws the original half-width area. The assertions now require pixels produced by replay, alongside preservation of the CPU-written right half.
  • The padded-array fixture now also covers storage snapshot, merge and refresh in imported memory at layer 1, preserving the existing CPU fallback. Distinct initial layer contents and completion of the initial upload make an incorrect baseline-layer offset observable. Full-buffer and refresh checks cover GPU results, CPU writes, padding and the untouched layer.

The follow-up was separately built and tested at 66f62d174: 36/36 focused executions passed, followed by five successful checks after the negative-control experiment was restored and rebuilt (agc_driver_graphics, plus resident and recipe on both GPUs). Temporarily removing the per-layer baseline offset made the new imported-snapshot assertion fail on both GPUs, with the CPU fallback still passing and no validation diagnostics. That mutation is absent from the commit. Convention and whitespace checks pass.

Please cherry-pick 66f62d17479bf7b393326c48926dea6bea31c6f0 if you would like to include this test tightening. The two 36-run results above belong to their respective commits; the follow-up is not yet part of this PR. No real-title, performance, Linux/macOS runtime or fresh full-suite result is claimed.

@embersas

Copy link
Copy Markdown

I rebuilt exact head e32a19b4d7957795a3b5cf21848b41889bd193a5 on an RTX 4070 Laptop GPU. The existing resident and cached-recipe tests pass, but an additional concurrent-byte regression exposes lost CPU stores.

Attached is a tested correction extending Rajveer Shekhawat’s implementation and MarcZX10’s integration. The seeded/unseeded regression derives from Celegans12’s reproduction. I’m offering this for integration into the existing PR.

Confirmed failures and correction

The concurrent regression uses a 64 × 4096 RGBA8 target. The GPU writes only blue while a CPU thread updates counters in red/green and checks the preceding values. On e32a19b4, it detected 5,668 lost CPU updates, although blue was correct and later CPU sweeps repaired the final counters. Checking only the final buffer misses this failure.

GPU word-level compare-and-swap does not provide atomicity with ordinary CPU stores to adjacent bytes. The correction uses a separate publication shader with write-only uint8_t storage-buffer stores, without destination loads or atomics. The driver already enables storageBuffer8BitAccess; ordinary detile/image variants remain unchanged.

A second regression exposed a stale-baseline problem: an actual GPU write equal to stale image contents can be omitted by the before/after comparison. PrepareLinearDraw now settles prior results and overlapping aliases, then uploads guest contents before taking the GPU baseline. This regression fails with the byte-store-only intermediate and passes with the complete correction.

The comparison is not treated as a write-coverage detector. It depends on establishing a coherent baseline first. Unsynchronized CPU/GPU stores to the same byte still require ordering. Publication remains in the recorded command stream, with the existing reader/host barriers and resource retention. The new checks use the established WaitIdle boundary without an additional test-only flush.

Tested

Hardware: NVIDIA GeForce RTX 4070 Laptop GPU, NVIDIA 592.82 / Windows driver 32.0.15.9282, Windows 11 Pro 10.0.26300. WinLibs GCC 15.2.0 r7, Release, Ninja; Khronos validation layer 1.4.363.0.

  • Rebuilt main 35fa2bdd824f1a77d5d70e7feeae85fd6d9baf04: 8 failures in 12 shared focused entries. The original unseeded regression preserves all 512 GPU pixels but overwrites 7,680/8,192 CPU-written bytes. Seeded and synchronous controls pass.
  • Corrected local revision fea0c0cd8a2e8f85454e0d4b5b917915e0e3035b: 15/15 focused tests pass, including concurrent CPU updates, queued draws, channel masks, partial geometry, dependent GPU copy and CPU-visible label, cache eviction, aliases, same-value writes, expanded resident coverage and cached-recipe replay.
  • After the main comparison, restored and rebuilt the correction: 15/15 pass again.
  • Four key cases repeated five times each: 20/20 executions pass, including zero lost CPU updates in every concurrent run. Same-output seeded/unseeded, sequential CPU-writer, direct-transfer reader and synchronous controls also pass.
  • Main uses the common runtime fixtures with identical assertions. The new same-value and expanded resident/recipe cases require APIs absent from main and are reported separately. Main’s original resident control passes; descriptor-capture mocks use the matching API version.

Every GPU run used:

ANYPS5_REQUIRE_VULKAN=1
ANYPS5_NO_SHADER_CACHE=1
ANYPS5_GPU=RTX 4070 Laptop
VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
VK_LOADER_DEBUG=layer
VK_LAYER_ENABLES=VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT

Actual validation-layer loading was verified. Base and correction logs contain zero VUIDs, synchronization hazards, missing-layer warnings or skips. The shared deprecated-setting notice is not counted as a new validation error.

Focused candidate command:

ctest --test-dir build-review-8152 -R '^agc_driver_(linear_target_(concurrent_bytes|cpu_writes.*|publication.*|resident|recipe)|graphics|alias_copy_label|array_layer_target)$' -V --timeout 30

Convention and whitespace checks pass. spirv-val --target-env vulkan1.1 accepts the publication shader; its compiled module has 8-bit storage, byte array stride 1 and no atomic operations.

The attachment is a plain unified diff against e32a19b4d7957795a3b5cf21848b41889bd193a5, without commit metadata. Apply it with git apply <attachment>.

SHA256: d7dbee013607048a06f05efea9b4ed3a4ab31086c1b396670e5ca4cf7b403bee

The additional upload/snapshot costs work and temporary memory. No game compatibility, performance improvement, Linux/macOS runtime, fresh full-suite or other-GPU result is claimed for this correction.

AI-assisted: yes.
8152-pr8246-followup.diff.txt

@MarcZX10
MarcZX10 force-pushed the codex/8152-linear-target-ordering branch from f063d00 to 030409a Compare October 20, 2026 11:00
@MarcZX10

Copy link
Copy Markdown
Contributor Author

Integrated the offered correction into #8246 as commit 030409ad4a86041c29fa65bf018632452d5b5cab after rebasing all three PR commits onto current main 891d5675150936bbb330a1f27bacc86113dd2532. The new commit preserves embersas as its author; the two Rajveer commits also retain their original author metadata.

The contributor-reported RTX 4070 Laptop run and correction-tree test results are recorded in the PR description, explicitly as pre-latest-rebase results. On the rebased head, git diff --check passes. The local conventions script stops at its duplicate-export scan with E2BIG, and hosted metadata checks were pending at the last poll. I could not run a current-head Vulkan build/runtime on this host.

@github-actions github-actions Bot added the docs label Oct 20, 2026
@wachi35676

Copy link
Copy Markdown
Contributor

This is a runtime run of the exact current head e32a19b4d, which was still outstanding. I merged it onto main 02fb1ce53 (a clean merge, after #8172).

Setup: Windows 11 (26300), WinLibs GCC 15.2.0, Release, BUILD_TESTING=ON. The GPUs are an RTX 5070 Ti (NVIDIA 617.42) and an AMD Radeon iGPU (AMD proprietary 2.0.353). Both runs used ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1; the validation layer was not used.

  • agc_driver_linear_target_resident passes 3 of 3 on each GPU. So do agc_storage_writeback_blocks, agc_write_tracking and agc_write_tracking_metadata_commit. The test logs linear target resident device: NVIDIA GeForce RTX 5070 Ti and ... AMD Radeon(TM) Graphics respectively.
  • Negative control: the PR's test uses PrepareLinearDraw, FinishLinearDraw and the new Dispatch overload, so it doesn't compile on main alone. Instead I kept the whole PR and restored only main's Draw.cpp, which removes the PrepareLinearDraw and FinishLinearDraw hook-up. The test then fails 2 of 2 on each GPU with unseeded scissor: write-back overwrote the CPU's untouched right half in row 0.
  • Related set of 75 tests (agc_driver_graphics, which includes the new TextureDetiler.cpp cases, plus storage, partially_resident, msaa, multisample, label, stencil, tessellation, write_tracking, resident and so on): 75 of 75 pass on each GPU. agc_driver_stencil_ref_export skips on NVIDIA because the GPU has no stencil export.

Not measured: the cost per draw. PrepareLinearDraw runs WriteBack() and then copies the whole image into a new 2x-size DeviceBuffer before every recorded draw into a resident linear target, and I have no title that exercises this path to time it.

AI-assisted: yes (Claude Code); results above were run on this machine.

Celegans12 added a commit to Celegans12/AnyPS5-Ghost-of-Yotei that referenced this pull request Oct 20, 2026
@Celegans12

Copy link
Copy Markdown
Contributor

I tested #8246 with Ghost of Yōtei (PPSA26344) on Windows 11 and an RTX 3080 Laptop, since #6892's resident linear targets are what broke our warm world runs in the first place. The unit-level fix holds up well on our tree. In the game, though, it doesn't fix the spawn: with resident linear targets on, Atsu still isn't at the river.

One caveat first: this isn't plain main. Our tree is main b509767 merged with our local Yōtei work (local/merge19 a5d6e17, where resident linear targets are opt-in behind APS5_RESIDENT_LINEAR=1). I applied your head 030409a on top as one diff. There were three small conflicts (Draw.cpp, Texture.cpp and the CMake test list), and I kept both sides in each. The shader cache version didn't change.

The tests all pass. Your new tests, the upstream resident-linear tests and the nearby storage and write-tracking tests went 22/22, three times each, with resident linear on. My #8152 reproducer passes 5/5 in both the seeded and the unseeded case. With only your Draw.cpp hooks taken out again, it fails 3/3 with 7,680 of the 8,192 right-half bytes rolled back, as before.

In the game, the warm run from our Ainu-village save never shows Atsu. From frame 078 on, the camera sits under the water looking up at the forest. That's the same family of symptoms as our earlier resident-linear runs (T-pose in the sky). With resident linear off, the same save spawns him at the river every time. The path does run there: in the world, about 15-43 recorded draws per 10 s go into resident linear targets, and each one gets your "linear draw baseline" upload.

I also wanted to know whether the game just reads those targets before the recorded write-back lands. So I added a local debug switch that does a full Recorder::Sync right after every recorded linear-target draw. That makes the write-back land before the next packet. It didn't help: the camera was still under the water. My guess is that the bytes reaching guest memory, or the resident image that the next draw starts from, are wrong in a case the tests don't cover, not that the order is wrong. I can't rule out an interaction with our local changes yet, though. Neither run lost the device or hit a GPU write fault.

frame 85: #8246 with resident linear on, the same with a sync after each linear draw, and resident linear off

If it helps, I can run an instrumented build next. For example, it could dump a linear target's guest bytes after one of these draws with resident linear on and off and diff them. Or I can try a newer head. Is there anything you'd want me to log in particular?

Details
  • Build: local/test-8246 = local/merge19 a5d6e17 + fix(agc): preserve CPU writes after resident linear target draws #8246 030409a as one commit (2339d4e) + the reproducer as its own execution test (LinearTargetRepro8152.cpp, from Celegans12/AnyPS5 repro/8152-linear-writeback b1c835f) + the debug switch (APS5_LINEAR_DRAW_SYNC, local only). SourceVersion 3b35146912b7970c, the same as without the PR. GCC 15.2.0 Release, NVIDIA RTX 3080 Laptop.
  • Tests (APS5_RESIDENT_LINEAR=1, ctest -j4 --repeat until-fail:3): agc_driver_linear_target_{resident, recipe, cpu_writes, cpu_writes_seeded, concurrent_bytes, publication, publication_mask/geometry/reader/eviction/alias/same, repro8152}, agc_driver_partially_resident_{snapshot, pending_stores}, agc_driver_uint8x4_color_target_no_resident, agc_resident_present, agc_storage_writeback_blocks, agc_write_tracking, agc_write_tracking_metadata_commit, agc_driver_graphics, linear_display_buffer: 22/22.
  • Reproducer [8152] lines with the PR, 5/5: seeded and unseeded, each with the second draw recorded, left half 0/512 pixels lost, right half 0/8192 bytes not the CPU's 0x42. Without the PR's PrepareLinearDraw/FinishLinearDraw hooks (Draw.cpp only), 3/3 failed: seeded 0/8192, unseeded 7680/8192.
  • World runs: warm, web-teshio-b save, pad script without jumps, our usual Yōtei env plus APS5_NO_DISPATCH_OVERLAP=1, stopped 10 s after frame_090.
    • Run 1 (APS5_RESIDENT_LINEAR=1): frame_078 at 247 s, frame_090 at 401 s. Frames 078-090 show the camera below the water surface, no Atsu.
    • Run 2 (also APS5_LINEAR_DRAW_SYNC=1): frame_090 at 365 s, frames 078-090 fog/water, no Atsu. Address-based syncs 3,675 → 4,233, so the switch fired.
    • Reference (APS5_RESIDENT_LINEAR unset, earlier run on merge19 045af03): Atsu at the river, frames 078-090.
  • Storage counters, per 10 s in the world: 15-43 "linear draw baseline" uploads (2-45 MiB), matched by as many "linear target" write-backs. During loading it reaches up to 157 (386 MiB). 0 host-heap refusals.
  • No frame-time comparison, because the broken runs render a much simpler scene than the river.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

@Celegans12, thanks for offering. A targeted capture on the current head 030409ad4a would help. If convenient, pick one linear target associated with the first incorrect water frame and record its guest address, dimensions/pitch/format, the guest bytes immediately before the draw baseline upload, the resident image bytes after the draw, and the guest bytes after write-back. The key is to identify the first point where those byte ranges diverge; no need for broad per-draw logging. If selecting a target is unclear, a newer-head run alone would still tell us whether the behavior changed.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed title run and the sync control. That changes the next question: the isolated CPU-write regressions pass, but this title still diverges even when each writeback is forced to complete before the next packet, so completion ordering alone does not explain the spawn failure. The most useful next capture would be the first target/draw that differs between resident-linear on and off: guest address, dimensions/format/pitch, bytes before the draw, resident image bytes after it, bytes written back, and the next consumer’s read. A narrow capture around the first divergence should distinguish stale baseline/image contents from a format/layout or alias mismatch. If you can share such a trace (or an instrumented reproducer), I can investigate the next fix in this PR.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

Thanks, this separates the #8152 byte-preservation case from the remaining Yōtei spawn failure: the focused CPU-write/repro tests and their negative control still validate the intended fix, while the title remains below water even with the per-draw sync switch. For the first affected target, could you log a compact identity (guest address, format, extent/pitch) and a hash plus a few sampled bytes at three points: after PrepareLinearDraw establishes the baseline, after the recorded draw completes just before its completion callback, and after WriteBack? That should show where the frame used for the spawn first diverges without dumping broad title memory. Comparing resident-linear off/on on the same saved state would help anchor it. There is no need to spend time timing the broken frame; I agree those scenes are not comparable.

@MarcZX10

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed run. The result narrows this down: the reproducer confirms the CPU write-back regression is fixed, while forcing a full sync after each recorded draw does not fix the Yōtei scene, so I agree we should look at the bytes and resident image contents rather than add more ordering waits.

If you can run one instrumented comparison, please pick a target touched during frames 078–090 and log/dump:

  • the target address/range, format, dimensions, pitch/tiling, and draw sequence number;
  • its guest-memory bytes after that draw's write-back has completed;
  • the same bytes immediately before the next draw that reads or writes the target; and
  • the corresponding resident-image contents at those two points, if the existing debug path can read them back.

Please capture resident-on and resident-off runs from the same save and report the first differing byte/pixel with the owning draw. A small bounded set around one target is enough; no need for a full frame dump. That should tell us whether the mismatch is in the write-back, the resident image used by the next draw, or another local Yōtei change.

MarcZX10 and others added 22 commits November 4, 2026 12:12
The detiler test checks that an ordinary detile has no baseline, that a changed-only dispatch binds the original with a sub-word offset, reuses one pipeline across baseline offsets and that ordinary retiling afterwards is unchanged.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
PrepareLinearDraw and FinishLinearDraw, and the buffer a linear draw keeps its original bytes in.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
PrepareLinearDraw writes back and flushes what is pending, uploads the target, then copies the image into a buffer that holds the bytes the draw started from next to a baseline copy; the recorder keeps the buffer and counts its bytes.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
FinishLinearDraw flushes the target's pending store and drops the snapshot once no layer is pending.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
…ass starts

recordDraw calls PrepareLinearDraw for every target, ahead of StartDrawPass.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
recordPreparedDraw does the same for the targets it binds when the draw is recorded.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
The completion store of a drawn linear target goes through FinishLinearDraw.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
Write-back compares the 64 KiB blocks written since the draw's snapshot and leaves the ones the CPU changed.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
A write-back that used the draw's snapshot publishes the whole shadow, not the partial units.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
The write-back detiles into the buffer the draw started from instead of a new one and keeps it with its size.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
…napshot

With a snapshot the write-back runs the changed-only detile against the draw's original bytes and no longer copies the tiled scratch over the import.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
A copy of the destination is taken before the store and the bytes the write-back did not change are put back, so concurrent CPU bytes survive.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
…napshot

main stores a drawn linear target through storeDrawnRect, which copies the whole drawn rectangle over the import and so overwrites the bytes of channels the draw masked out that the CPU wrote since. A target with a draw snapshot already stores only the bytes that changed, so writeBackLayers takes the rectangle path only when there is no snapshot.
Resources, the detiler and the standard headers it now uses.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
…rget

A left-half geometry and a program whose blue constant can be chosen.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
…k and vertices

The draw helper can halve the destination with blending, restrict the color write mask and the scissor, and take its own vertices.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
…in the resident test

The resident test gets a Coverage mode, the APS5_NO_RESIDENT_LINEAR flag, checks of queued and cached draws and of the bytes a draw leaves alone, a CPU snapshot check, a changed-only retile check and a --recipe mode that replays the draw through a draw recipe.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
agc_driver_linear_target_recipe runs agc_driver_linear_target_resident_tests --recipe.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
Draws into a linear target while the CPU writes other bytes of it and checks that the CPU's bytes are kept.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
Six cases (mask, geometry, reader, eviction, alias, same) check what a resident linear target publishes after a draw; registered per case.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
A CPU-write regression with two switches, APS5_LINEAR_SAME_OUTPUT and APS5_LINEAR_SEED_LEFT, and a seeded registration; the switches are documented in ENVIRONMENT.md.

Co-authored-by: Rajveer Shekhawat <rajveershekhawat626@gmail.com>
Co-authored-by: embersas <30363137+embersas@users.noreply.github.com>
…he whole target

The write-back of the previous draw leaves the image current, so the forced whole-surface upload before every recorded draw copied bytes the image already held. Refresh uploads only the layers whose guest memory changed since the image was last current, which includes the CPU's writes.
@MarcZX10
MarcZX10 force-pushed the codex/8152-linear-target-ordering branch from 9377004 to 8868994 Compare November 4, 2026 12:16
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 4, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 8868994 merged onto main 9ab6a28 · tested 2026-11-04 22:15 UTC · 35 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,872 passed · 5 failed (0 new, 3 also fail on main, 2 unstable on main) · 48 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,925 of 3,909 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (993 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) none
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_submit_progress: failed in 3 of the last 10 main runs
agc_submit_progress: failed in 4 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (3, not in the main baseline's validation pass)
agc_driver_linear_target_concurrent_bytes
agc_driver_linear_target_preserved_bytes
agc_driver_linear_target_publication
Validation IDs already present on main (13 IDs in 554 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (554 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, and 546 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08739 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08741 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
VUID-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (48)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: s
Reproduce
git fetch origin 8868994b056bec151255bb8248165594bd2b4d33 9ab6a281ea61c9e62a7eb07eb4cef8f19ede1c5c
git checkout 9ab6a281ea61c9e62a7eb07eb4cef8f19ede1c5c && git merge --no-ff 8868994b056bec151255bb8248165594bd2b4d33
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 4, 2026
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 5, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 3ab861c merged onto main e9247a9 · tested 2026-11-05 23:18 UTC · 25 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,981 passed · 4 failed (0 new, 3 also fail on main, 1 unstable on main) · 57 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 3,042 of 4,105 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (990 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.2 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 1 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)
agc_driver_submit_progress: Failed in the parallel run; also passed only on retry in 30 other runs in the last 7 days
Validated but not compared (3, not in the main baseline's validation pass)
agc_driver_linear_target_concurrent_bytes
agc_driver_linear_target_preserved_bytes
agc_driver_linear_target_publication
Validation IDs already present on main (9 IDs in 593 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (593 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, and 585 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08739 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08741 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
VUID-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
Skipped (57)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_net_ctl_disconnected: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_device_capability: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_disabled: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_four_k: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_height_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_limit: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_malformed: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_width_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current 
Reproduce
git fetch origin 3ab861cd08dae4aa651627e0bacc861418710b40 e9247a966ff6cce55816ffe1d73a2679074348a4
git checkout e9247a966ff6cce55816ffe1d73a2679074348a4 && git merge --no-ff 3ab861cd08dae4aa651627e0bacc861418710b40
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the rebase. Against the last review, using @savvaniss's rerun on 9377004c3c (same commit as the perf(agc) one on this head; later pushes are merges of main):

  • Memory is still unbounded per draw: device-local usage grows about 71 MiB per recorded draw against about 24 MiB on base (12,901 MiB vs 4,333 MiB at 180 draws in one frame; peak private commit 13.2 GiB vs 4.6 GiB). Please bound the snapshots (release or reuse them per draw, or cap how many are live) and post peak device-local memory before/after at 60 and 180 draws, see the memory section of CONTRIBUTING.
  • New stall: at 180 draws per frame the slowest single draw is 315 to 397 ms in every run (5,036 ms once at 150), against 7 to 10 ms on base. It looks like waiting on the frame's queued work while device-local memory is near 11 to 13 GiB. Please find what triggers it; the memory bound above may be the fix.
  • agc_driver_linear_target_publication_alias failed with wrong CPU bytes=557056 on 9377004c3c on both AMD (write-watched) and NVIDIA. The NVIDIA run on the current head passes with no new validation IDs. Please say what fixed it, and rerun it on a write-watched host (Windows) to confirm.
  • First-frame cost: savvaniss measured about +170 ms in frame 0 (mostly in WaitIdle) and later frames waiting about half as long as base. Please say what the first frame pays for.
  • Minor: the Tested line still says the validation run on main is not posted; update it with the results above.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs fix error Closes an issue (Fixes #N)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AGC: a recorded draw into a resident linear color target stores the whole target back over CPU stores made after the draw